﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Dwarf.Managed
{
    /// <summary>
    /// Solve the Structured Grid problem with Serial parallelization  
    /// </summary>
    /// <remarks> 
    /// For the demonstration purposes of the project, we have chosen solution of Laplace's equation 
    /// with the Dirichlet’s conditions on the square. To obtain solution, iterated Jacobi method is applied. 
    /// It consists of steps like:
    /// newgrid[i,j] = (grid[i-1,j] + grid[i+1,j] + grid[i,j - 1] + grid[I,j + 1]) / 4
    /// </remarks>
    class Solver
    {
        /// <summary>
        /// The number of columns.
        /// </summary>
        public int xmax;

        /// <summary>
        /// The number of rows.
        /// </summary>
        public int ymax;

        /// <summary>
        /// Epsilon.
        /// </summary>
        public double epsilon;

        /// <summary>
        /// Initial matrix.
        /// </summary>
        public double[][] grid;

        /// <summary>
        /// Temp matrix.
        /// </summary>
        public double[][] tempGrid;

        /// <summary>
        /// Iterations to Convergence.
        /// </summary>
        public long iterations;


        /// <summary>
        /// Empty constructor.
        /// </summary>
        public Solver()
        {
        }

        /// <summary>
        /// Serial based method.
        /// </summary>
        public void Solve()
        {
            iterations = 0;
            bool converged = false;                 //Flag of convergance

            while (!converged)                                                                                          //Main looop
            {
                iterations++;
                converged = true;

                for (int i = 1; i < ymax - 1; i++)                                                                          // Loop for number of rows in matrix.
                {
                    //Since C# compiler/runtime is not hoisting 
                    double[] above = grid[i - 1];
                    double[] row = grid[i];
                    double[] below = grid[i + 1];
                    double[] newRow = tempGrid[i];
                    for (int j = 1; j < xmax - 1; j++)                                                                      // Loop for number of columns in matrix.
                    {
                        //Perform step of computation on current node
                        double cell = newRow[j] = 0.25 * (above[j] + below[j] + row[j - 1] + row[j + 1]);

                        converged = converged && (Math.Abs(cell - row[j]) < epsilon);         // Check test of convergence for current node                     }
                    }
                }

                //swap newly computed tempGrid and grid to get ready for next interation
                double[][] swap = grid;
                grid = tempGrid;
                tempGrid = swap;
            }
        }
    }
}
